package ru.urfc.portal.ui.client.controllers;

import ru.urfc.portal.ui.client.controllers.loaders.ConfigurableLoader;
import ru.urfc.portal.ui.client.descriptor.GridDescriptor;
import ru.urfc.portal.ui.client.descriptor.GridField;
import ru.urfc.portal.ui.client.renderers.UrlRenderer;

import com.extjs.gxt.ui.client.data.LoadEvent;
import com.extjs.gxt.ui.client.data.Loader;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.BaseObservable;
import com.extjs.gxt.ui.client.event.EventType;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.LoadListener;
import com.extjs.gxt.ui.client.event.Observable;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.EventHandler;

public abstract class BaseController implements EventHandler {
	
	protected Observable observable = new BaseObservable();
	protected GridDescriptor descriptor;
	private LoaderHandler loaderHandler;
	private ErrorReporter errorReporter = ErrorReporter.NO_REPORTER;
	
	private boolean hasPatchedUrls = false;

	protected BaseController(final GridDescriptor descriptor) {
		this.descriptor = descriptor;
		this.loaderHandler = new LoaderHandler(descriptor, createLoader(descriptor));
		loaderHandler.addListener(Loader.LoadException, new LoadListener() {
			@Override
			public void loaderLoadException(LoadEvent event) {
				onFailure(event.exception);
			}
		});
	}	

	protected abstract ConfigurableLoader<?> createLoader(GridDescriptor descriptor);	

	public void patchUrls(boolean debugMode, String debugArg) {
		if (debugMode && !this.hasPatchedUrls) {
			for (GridField gridField: descriptor.getAssignedFields()) {
				if (gridField.getRenderer() instanceof UrlRenderer) {
					UrlRenderer renderer = gridField.getRenderer();
					renderer.patchUrlTemplate(debugArg);
				}
			}
			this.hasPatchedUrls = debugMode;
		}
	}
	
	boolean hasPatchedUrls() {
		return hasPatchedUrls;
	}

	private void onFailure(Throwable t) {
		errorReporter.reportError("(нет доступа к данным)");
		if (!GWT.isScript()) {
			GWT.log("failed loading from " + descriptor.getRestUrl(), t);
			showMessage("Request parsing " + descriptor.getRestUrl() + " failed. " + t.getMessage());
		}
	}
	
	public void setErrorReporter(ErrorReporter errorReporter) {
		this.errorReporter = errorReporter;
	}
	
	protected void showMessage(String message) {
		MessageBox.alert("Ошибка:", message, null);
	};
	
	public void doGet() {
		loaderHandler.loadWithGet();
	}
	
	public void doDelete() {
		loaderHandler.loadWithDelete();
	}

	public void doPost(String data) {
		loaderHandler.loadWithPost(data);
	}

	public void doPut(String data) {
		loaderHandler.loadWithPut(data);
	}

	public void addListener(EventType eventType, Listener<? extends BaseEvent> listener) {
		observable.addListener(eventType, listener);
	}

}